package com.github.easyms.server.service.auth.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.easyms.common.constant.AuthConstants;
import com.github.easyms.common.constant.EasymsServiceStatus;
import com.github.easyms.common.constant.GlobalConstants;
import com.github.easyms.common.entity.auth.Menu;
import com.github.easyms.common.entity.auth.User;
import com.github.easyms.common.exception.EasymsException;
import com.github.easyms.common.util.StringHelper;
import com.github.easyms.common.vo.EasymsPage;
import com.github.easyms.common.vo.auth.ChildAuthMenuVo;
import com.github.easyms.common.vo.auth.ParentAuthMenuVo;
import com.github.easyms.server.mapper.auth.MenuMapper;
import com.github.easyms.server.service.auth.MenuService;
import com.github.easyms.server.service.auth.RoleMenuService;
import com.google.common.collect.Lists;
import io.swagger.annotations.Api;
import org.apache.shiro.SecurityUtils;
import org.apache.tomcat.jni.Local;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 菜单数据业务实现
 *
 * @author Leo.Liao
 * @date 2020-04-28 23:40:09
 */
@Service("menuService")
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements MenuService {

    @Resource
    private MenuMapper menuMapper;

    @Resource
    private RoleMenuService roleMenuService;

    @Override
    public <E extends IPage<Menu>> E page(E page) {
        EasymsPage<Menu> easymsPage = (EasymsPage<Menu>) page;
        Menu condition = easymsPage.getCondition();
        E resultPage = super.page(page, Wrappers.<Menu>lambdaQuery()
                .isNotNull(Menu::getPmenuId)
                .eq(!StringHelper.isEmpty(condition.getPmenuId()),Menu::getPmenuId,condition.getPmenuId())
                .eq(!StringHelper.isEmpty(condition.getMenuType()),Menu::getMenuType,condition.getMenuType())
                .eq(!StringHelper.isEmpty(condition.getStatus()),Menu::getStatus,condition.getStatus())
        );
        return resultPage;
    }

    @Override
    public boolean save(Menu entity) {
        entity.setCreateTime(LocalDateTime.now());
        return super.save(entity);
    }

    @Override
    public boolean updateById(Menu entity) {
        entity.setUpdateTime(LocalDateTime.now());
        return super.updateById(entity);
    }

    @Override
    public boolean removeById(Serializable id) {
        Menu menu = (Menu) id;
        roleMenuService.deleteByMenuId(menu.getMenuId());
        return super.removeById(id);
    }

    @Override
    public List<ParentAuthMenuVo> getAuthMenuTree(String roleId, String language) {

        List<ParentAuthMenuVo> authMenuVos = Lists.newLinkedList();

        // 1.查询角色权限菜单ids
        List<String> menuIds = Lists.newArrayList();

        // 如果角色ID不为空，则查本角色的权限菜单ID列表
        if(roleId != null){
            List<String> tempList = roleMenuService.selectMenuIdsByRoleId(roleId);
            if(tempList == null || tempList.size() == 0){
                throw new EasymsException(EasymsServiceStatus.NO_ROLES);
            }
            menuIds.addAll(tempList);
        }

        // 2.查询父菜单
        List<Menu> parentMenus = menuMapper.selectList(Wrappers.<Menu>lambdaQuery()
                .eq(Menu::getMenuType, AuthConstants.MenuType.PARENT)
                .eq(Menu::getStatus, GlobalConstants.DataStatus.ACTIVE)
                // 角色ID不为空时，查本角色对应的菜单信息
                .in(!StringHelper.isEmpty(roleId),Menu::getMenuId, menuIds)
                .orderByAsc(Menu::getSorting)
        );
        // 3.查询子菜单（in ids）
        parentMenus.forEach(parentMenu -> {

            ParentAuthMenuVo parentAuthMenuVo = new ParentAuthMenuVo();
            parentAuthMenuVo.setId(parentMenu.getMenuId());
            parentAuthMenuVo.setIconCls(parentMenu.getIconCls());
            parentAuthMenuVo.setState(AuthConstants.MenuState.CLOSED);
            parentAuthMenuVo.setText(switchMenuTextByLang(language,parentMenu));
            parentAuthMenuVo.setUrl(parentMenu.getUrl());

            List<Menu> childMenus = menuMapper.selectList(Wrappers.<Menu>lambdaQuery()
                    .eq(Menu::getMenuType, AuthConstants.MenuType.CHILD)
                    .eq(Menu::getPmenuId,parentMenu.getMenuId())
                    .eq(Menu::getStatus, GlobalConstants.DataStatus.ACTIVE)
                    // 角色ID不为空时，查本角色对应的菜单信息
                    .in(!StringHelper.isEmpty(roleId),Menu::getMenuId, menuIds)
                    .orderByAsc(Menu::getSorting)
            );

            List<ChildAuthMenuVo> childAuthMenuVos = Lists.newLinkedList();
            childMenus.forEach(childMenu ->{
                ChildAuthMenuVo childAuthMenuVo = new ChildAuthMenuVo();
                childAuthMenuVo.setId(childMenu.getMenuId());
                childAuthMenuVo.setText(switchMenuTextByLang(language,childMenu));
                childAuthMenuVo.setUrl(childMenu.getUrl());
                childAuthMenuVo.setIconCls(childMenu.getIconCls());
                childAuthMenuVos.add(childAuthMenuVo);
            });

            parentAuthMenuVo.setChildren(childAuthMenuVos);
            authMenuVos.add(parentAuthMenuVo);

        });

        return authMenuVos;
    }

    @Override
    public List<ParentAuthMenuVo> getCheckedAuthMenuTree(String roleId, String language) {

        List<ParentAuthMenuVo> authMenuVos = Lists.newLinkedList();

        // 1.查询角色权限菜单ids
        List<String> menuIds = roleMenuService.selectMenuIdsByRoleId(roleId);

        // 2.查询父菜单
        List<Menu> parentMenus = menuMapper.selectList(Wrappers.<Menu>lambdaQuery()
                .eq(Menu::getMenuType, AuthConstants.MenuType.PARENT)
                .eq(Menu::getStatus, GlobalConstants.DataStatus.ACTIVE)
                .isNotNull(Menu::getPmenuId)
                .orderByAsc(Menu::getSorting)
        );

        // 3.查询子菜单
        parentMenus.forEach(parentMenu -> {

            ParentAuthMenuVo parentAuthMenuVo = new ParentAuthMenuVo();
            parentAuthMenuVo.setId(parentMenu.getMenuId());
            parentAuthMenuVo.setIconCls(parentMenu.getIconCls());
            parentAuthMenuVo.setState(AuthConstants.MenuState.OPEN);
            parentAuthMenuVo.setText(switchMenuTextByLang(language,parentMenu));
            parentAuthMenuVo.setUrl(parentMenu.getUrl());

            // 查询一级菜单下的子菜单
            List<Menu> childMenus = menuMapper.selectList(Wrappers.<Menu>lambdaQuery()
                    .eq(Menu::getMenuType, AuthConstants.MenuType.CHILD)
                    .eq(Menu::getPmenuId,parentMenu.getMenuId())
                    .eq(Menu::getStatus, GlobalConstants.DataStatus.ACTIVE)
                    .orderByAsc(Menu::getSorting)
            );

            List<ChildAuthMenuVo> childAuthMenuVos = Lists.newLinkedList();

            childMenus.forEach(childMenu ->{
                ChildAuthMenuVo childAuthMenuVo = new ChildAuthMenuVo();
                childAuthMenuVo.setId(childMenu.getMenuId());
                childAuthMenuVo.setText(switchMenuTextByLang(language,childMenu));
                childAuthMenuVo.setUrl(childMenu.getUrl());
                childAuthMenuVo.setIconCls(childMenu.getIconCls());
                if(menuIds.contains(childMenu.getMenuId())){
                    childAuthMenuVo.setChecked(true);
                }
                childAuthMenuVos.add(childAuthMenuVo);
            });

            parentAuthMenuVo.setChildren(childAuthMenuVos);
            authMenuVos.add(parentAuthMenuVo);

        });

        return authMenuVos;
    }

    @Override
    public List<Menu> listCombobox(Menu entity,String language,String q) {
        List<Menu> menuList = Lists.newLinkedList();
        List<Menu> menus = menuMapper.selectList(Wrappers.<Menu>lambdaQuery()
                .like(!StringHelper.isEmpty(q), Menu::getText, q)
                .eq(!StringHelper.isEmpty(entity.getMenuType()), Menu::getMenuType, entity.getMenuType())
                .eq(Menu::getStatus, GlobalConstants.DataStatus.ACTIVE)
                .orderByAsc(Menu::getSorting)
                .last("limit 20")
        );
        menus.forEach(menu -> {
            String menuName = switchMenuTextByLang(language, menu);
            menu.setText(menuName);
            menuList.add(menu);
        });
        return menuList;
    }

    /**
     * 根据语言值选择菜单名称
     * @param language
     * @param menu
     * @return
     */
    private String switchMenuTextByLang(String language,Menu menu){
        JSONObject jsonObject = JSON.parseObject(menu.getText());
        String menuText = jsonObject.getString(language);
        return menuText;
    }
}
